using System;
using System.Runtime.Serialization;

namespace BanZuiCloudControlAgent.Utils.Exceptions
{
    /// <summary>
    /// EMQX相关异常类，用于表示EMQX连接、消息发布、订阅等过程中发生的错误
    /// </summary>
    [Serializable]
    public class EmqxException : BanZuiException
    {
        /// <summary>
        /// EMQX错误类型
        /// </summary>
        public EmqxErrorType ErrorType { get; }

        /// <summary>
        /// 主题名称（如果适用）
        /// </summary>
        public string Topic { get; }

        /// <summary>
        /// 初始化EmqxException类的新实例
        /// </summary>
        public EmqxException() : base("E200", "EMQX", "EMQX操作发生错误")
        {
            ErrorType = EmqxErrorType.Unknown;
            Topic = null;
        }

        /// <summary>
        /// 使用指定的错误消息初始化EmqxException类的新实例
        /// </summary>
        /// <param name="message">描述错误的消息</param>
        public EmqxException(string message) : base("E200", "EMQX", message)
        {
            ErrorType = EmqxErrorType.Unknown;
            Topic = null;
        }

        /// <summary>
        /// 使用指定的错误消息和内部异常初始化EmqxException类的新实例
        /// </summary>
        /// <param name="message">描述错误的消息</param>
        /// <param name="innerException">导致当前异常的异常</param>
        public EmqxException(string message, Exception innerException) : base("E200", "EMQX", message, false, innerException)
        {
            ErrorType = EmqxErrorType.Unknown;
            Topic = null;
        }

        /// <summary>
        /// 使用指定的错误类型和消息初始化EmqxException类的新实例
        /// </summary>
        /// <param name="errorType">EMQX错误类型</param>
        /// <param name="message">描述错误的消息</param>
        public EmqxException(EmqxErrorType errorType, string message) : base(GetErrorCode(errorType), "EMQX", message)
        {
            ErrorType = errorType;
            Topic = null;
        }

        /// <summary>
        /// 使用指定的错误类型、消息和内部异常初始化EmqxException类的新实例
        /// </summary>
        /// <param name="errorType">EMQX错误类型</param>
        /// <param name="message">描述错误的消息</param>
        /// <param name="innerException">导致当前异常的异常</param>
        public EmqxException(EmqxErrorType errorType, string message, Exception innerException) : base(GetErrorCode(errorType), "EMQX", message, false, innerException)
        {
            ErrorType = errorType;
            Topic = null;
        }

        /// <summary>
        /// 使用指定的错误类型、主题和消息初始化EmqxException类的新实例
        /// </summary>
        /// <param name="errorType">EMQX错误类型</param>
        /// <param name="topic">主题名称</param>
        /// <param name="message">描述错误的消息</param>
        public EmqxException(EmqxErrorType errorType, string topic, string message) : base(GetErrorCode(errorType), "EMQX", message)
        {
            ErrorType = errorType;
            Topic = topic;
        }

        /// <summary>
        /// 使用指定的错误类型、主题、消息和内部异常初始化EmqxException类的新实例
        /// </summary>
        /// <param name="errorType">EMQX错误类型</param>
        /// <param name="topic">主题名称</param>
        /// <param name="message">描述错误的消息</param>
        /// <param name="innerException">导致当前异常的异常</param>
        public EmqxException(EmqxErrorType errorType, string topic, string message, Exception innerException) : base(GetErrorCode(errorType), "EMQX", message, false, innerException)
        {
            ErrorType = errorType;
            Topic = topic;
        }

        /// <summary>
        /// 使用序列化数据初始化EmqxException类的新实例
        /// </summary>
        /// <param name="info">SerializationInfo，它存有关于所引发的异常的序列化的对象数据</param>
        /// <param name="context">包含有关源或目标的上下文信息</param>
        protected EmqxException(SerializationInfo info, StreamingContext context) : base(info, context)
        {
            ErrorType = (EmqxErrorType)info.GetInt32("ErrorType");
            Topic = info.GetString("Topic");
        }

        /// <summary>
        /// 使用可序列化的数据填充SerializationInfo
        /// </summary>
        /// <param name="info">要填充数据的SerializationInfo</param>
        /// <param name="context">此序列化的目标</param>
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
            info.AddValue("ErrorType", (int)ErrorType);
            info.AddValue("Topic", Topic);
        }

        /// <summary>
        /// 获取包含错误代码、主题的完整错误消息
        /// </summary>
        /// <returns>包含错误代码、主题的完整错误消息</returns>
        public override string ToString()
        {
            if (string.IsNullOrEmpty(Topic))
            {
                return base.ToString();
            }
            return $"[{ErrorCode}] {Module} (Topic: {Topic}): {Message}";
        }

        /// <summary>
        /// 根据EMQX错误类型获取错误代码
        /// </summary>
        /// <param name="errorType">EMQX错误类型</param>
        /// <returns>错误代码</returns>
        private static string GetErrorCode(EmqxErrorType errorType)
        {
            switch (errorType)
            {
                case EmqxErrorType.ConnectionFailed:
                    return "E201";
                case EmqxErrorType.ConnectionLost:
                    return "E202";
                case EmqxErrorType.PublishFailed:
                    return "E203";
                case EmqxErrorType.SubscribeFailed:
                    return "E204";
                case EmqxErrorType.UnsubscribeFailed:
                    return "E205";
                case EmqxErrorType.AuthenticationFailed:
                    return "E206";
                case EmqxErrorType.InvalidTopic:
                    return "E207";
                case EmqxErrorType.InvalidMessage:
                    return "E208";
                case EmqxErrorType.NotConnected:
                    return "E209";
                case EmqxErrorType.DisconnectionFailed:
                    return "E210";
                case EmqxErrorType.ListenerStartFailed:
                    return "E211";
                case EmqxErrorType.ListenerStopFailed:
                    return "E212";
                default:
                    return "E200";
            }
        }
    }

    /// <summary>
    /// EMQX错误类型枚举
    /// </summary>
    public enum EmqxErrorType
    {
        /// <summary>
        /// 未知错误
        /// </summary>
        Unknown = 0,

        /// <summary>
        /// 连接失败
        /// </summary>
        ConnectionFailed = 1,

        /// <summary>
        /// 连接断开
        /// </summary>
        ConnectionLost = 2,

        /// <summary>
        /// 发布消息失败
        /// </summary>
        PublishFailed = 3,

        /// <summary>
        /// 订阅主题失败
        /// </summary>
        SubscribeFailed = 4,

        /// <summary>
        /// 取消订阅失败
        /// </summary>
        UnsubscribeFailed = 5,

        /// <summary>
        /// 认证失败
        /// </summary>
        AuthenticationFailed = 6,

        /// <summary>
        /// 无效的主题
        /// </summary>
        InvalidTopic = 7,

        /// <summary>
        /// 无效的消息
        /// </summary>
        InvalidMessage = 8,

        /// <summary>
        /// 未连接
        /// </summary>
        NotConnected = 9,

        /// <summary>
        /// 断开连接失败
        /// </summary>
        DisconnectionFailed = 10,

        /// <summary>
        /// 消息监听器启动失败
        /// </summary>
        ListenerStartFailed = 11,

        /// <summary>
        /// 消息监听器停止失败
        /// </summary>
        ListenerStopFailed = 12
    }
} 